home *** CD-ROM | disk | FTP | other *** search
- /* This is a C version of the Port Handler
- * Andy Finkel
- * Copyright (c) 1988 Commodore-Amiga, Inc.
- *
- * Executables based on this information may be used in software
- * for Commodore Amiga computers. All other rights reserved.
- *
- * This information is provided "as is"; no warranties are made.
- * All use is at your own risk, and no liability or
- * responsibility is assumed.
- *
- * This version is Mounted, rather than automatically called, since
- * DOS.Library seems to call the Port-handler assuming it is a
- * BCPL program, for some reason.
- *
- * The mountlist entries for this handler are as follows:
- * cser: Handler= L:CPort-Handler
- * Priority=5
- * StackSize=2000
- * GlobVec = -1
- *#
- * cpar: Handler= L:CPort-Handler
- * Priority=5
- * StackSize=2000
- * GlobVec = -1
- *#
- * cprt: Handler= L:CPort-Handler
- * Priority=5
- * StackSize=2000
- * GlobVec = -1
- *#
- */
-
- #include "exec/types.h"
- #include "exec/nodes.h"
- #include "exec/lists.h"
- #include "exec/ports.h"
- #include "exec/libraries.h"
- #include "exec/devices.h"
- #include "exec/io.h"
- #include "exec/memory.h"
- #include "libraries/dos.h"
- #include "libraries/dosextens.h"
- #include "libraries/filehandler.h"
- #include "devices/serial.h"
- #include "devices/parallel.h"
- #include "devices/printer.h"
-
- union pio {
- struct IOStdReq ios;
- struct IODRPReq iodrp;
- struct IOPrtCmdReq iopc;
- struct IOExtSer ioser;
- struct IOExtPar iopar;
- };
-
-
- #define DOS_TRUE -1
- #define IOSIZE sizeof(union pio)
-
- #define QTOUPPER(c) ((c)>='a'&&(c)<='z'?(c)-'a'+'A':(c))
-
- /* internal packets */
- #define action_read 1001
- #define action_write 1002
-
- #define ACTION_FIND_INPUT 1005
- #define ACTION_FIND_OUTPUT 1006
- #define ACTION_END 1007
-
- #undef BADDR
- #define BADDR(x) ((CPTR)((LONG)x << 2))
-
- extern struct DosPacket *taskwait();
- extern VOID setIO();
- extern VOID sendIO();
- extern VOID returnpkt();
-
- extern struct ExecBase *AbsExecBase;
- struct ExecBase *SysBase;
- struct DOSLibrary *DOSBase;
-
- main()
- {
-
- ULONG i;
- UBYTE *openstring;
- UBYTE *devname;
- BOOL error;
- BOOL printer=FALSE;
- BOOL OpenForInput = FALSE, OpenForOutput = FALSE;
-
- struct DeviceNode *node; /* our device node is passed in parm pkt Arg3 */
-
- struct DosPacket *packet;
- struct FileHandle *scb;
-
- struct DosPacket inp;
- struct DosPacket *inpkt;
- struct DosPacket out;
- struct DosPacket *outpkt;
-
- struct DosPacket *readPkt;
- struct DosPacket *writePkt;
-
- struct IOStdReq *iob;
- struct IOStdReq *iobo;
-
- struct MsgPort *devport;
- struct Process *process;
-
- SysBase = AbsExecBase;
-
- process=(struct Process *) FindTask(NULL);
- devport = &process->pr_MsgPort;
- inpkt = &inp;
- outpkt = &out;
-
- packet = taskwait(); /* wait for parm. packet */
-
- /* openstring tells which we are supposed to be...prt, par, or ser */
- openstring = (UBYTE *)BADDR(packet->dp_Arg1);
- node = (struct DeviceNode *) BADDR(packet->dp_Arg3);
-
- /* we need DOS.library to unload ourselves later */
- DOSBase = (struct DosLibrary *) OpenLibrary("dos.library",0);
-
- if(!strcmpi(openstring,"cprt:")) {
- printer = DOS_TRUE;
- devname = "printer.device";
- }
- else if (!strcmpi(openstring,"cpar:"))devname = "parallel.device";
- else devname = "serial.device";
-
- /* set up the input IOR and the output IOR */
- iob=(struct IOStdReq *)CreateExtIO(devport,(LONG)IOSIZE);
- iobo=(struct IOStdReq *)CreateExtIO(devport,(LONG)IOSIZE);
- if(!iob || !iobo) goto exit;
-
- /* open the device */
- if(error=OpenDevice(devname,0,iob, 0)) {
- returnpkt(packet,FALSE,ERROR_OBJECT_IN_USE);
- goto exit;
- }
- *iobo = *iob; /* copy input req to output req */
-
- /* Turn CR conversion off if raw mode is selected for printer */
- if (printer) { /* must be cprt: or cprt:raw */
- if(strlen(openstring) > 5) {
- setIO(iobo,CMD_WRITE,"\033[20l",5);
- DoIO(iobo);
- }
- }
-
- /* patch outselves into the system */
-
- outpkt->dp_Type = action_write;
- inpkt->dp_Type = action_read;
- node->dn_Task = devport;
-
- /* Finished with parameter packet...send back...*/
- returnpkt(packet,DOS_TRUE,packet->dp_Res2);
-
- /* Main Event Loop */
- do {
- packet = taskwait();
- switch (packet->dp_Type) {
-
- case ACTION_FIND_INPUT:
- scb = (struct FileHandle *) BADDR(packet->dp_Arg1);
- if (OpenForInput) {
- returnpkt(packet,FALSE,ERROR_OBJECT_IN_USE);
- continue;
- }
- OpenForInput = DOS_TRUE;
- /* now mark as interactive */
- scb->fh_Port = (struct MsgPort *)DOS_TRUE;
- scb->fh_Arg1 = ACTION_FIND_INPUT;
- returnpkt(packet,DOS_TRUE,0);
- continue;
-
- case ACTION_FIND_OUTPUT:
- scb = (struct FileHandle *) BADDR(packet->dp_Arg1);
- if(OpenForOutput) {
- returnpkt(packet,FALSE,ERROR_OBJECT_IN_USE);
- continue;
- }
- OpenForOutput = DOS_TRUE;
- /* set interactive flag */
- scb->fh_Port = (struct MsgPort *)DOS_TRUE;
- scb->fh_Arg1 = ACTION_FIND_OUTPUT;
- returnpkt(packet,DOS_TRUE,0);
- continue;
-
- case ACTION_END: /* Close request */
- if (packet->dp_Arg1 == ACTION_FIND_INPUT) OpenForInput = FALSE;
- else OpenForOutput = FALSE;
- if(!OpenForInput && !OpenForOutput)node->dn_Task = 0;
- returnpkt(packet,DOS_TRUE,0);
- continue;
-
- case action_read: /* Read request returning */
- inpkt = packet;
- handleReturn(iob,readPkt);
- continue;
-
- case action_write: /* Write request returning */
- outpkt = packet;
- handleReturn(iobo,writePkt);
- continue;
-
- case 'R': /* Read Request */
- readPkt = packet;
- handleRequest(iob,CMD_READ,packet,inpkt);
- inpkt = 0;
- continue;
-
- case 'W': /* Write Request */
- writePkt = packet;
- handleRequest(iobo,CMD_WRITE,packet,outpkt);
- outpkt = 0;
- continue;
-
- default:
- if(!OpenForInput && !OpenForOutput) node->dn_Task = 0;
- returnpkt(packet,FALSE,ERROR_ACTION_NOT_KNOWN);
- }
- } while (OpenForInput || OpenForOutput || (outpkt==0) || (inpkt==0));
-
- exit:
- if(!error)CloseDevice(iob);
- if(iob)DeleteExtIO(iob,(ULONG)IOSIZE);
- if(iobo)DeleteExtIO(iobo,(ULONG)IOSIZE);
-
- /* This looks funny, but works because DOS is not part of the code being unloaded */
- Forbid();
- UnLoadSeg(node->dn_SegList);
- CloseLibrary(DOSBase);
- node->dn_SegList=0;
- }
-
- /* Handle an IO request. Passed command, transmission packet (tp)
- and request packet (rp). rp contains buffer and length in arg2/3. */
-
- handleRequest(iob, command, rp, tp )
- struct IOStdReq *iob;
- ULONG command;
- struct DosPacket *rp;
- struct DosPacket *tp;
- {
- UBYTE *buff = (UBYTE *)rp->dp_Arg2;
- int len = (int)rp->dp_Arg3;
-
- setIO( iob, command, 0, rp->dp_Arg3, 0 );
- iob->io_Data = buff;
- sendIO( iob, tp );
- }
-
- /* Handle a returning IO request. The user request packet is
- passed as packet, and must be returned with success/failure message. */
-
- handleReturn(iob, packet )
- struct IOStdReq *iob;
- struct DosPacket *packet;
- {
- int errcode = iob->io_Error;
- int len=iob->io_Actual;
-
- if( errcode==0) returnpkt(packet, len ,0);
- else returnpkt(packet, -1, errcode );
- }
-
- /* Initialize IO request block */
-
- VOID setIO(iob,cmd,data,len)
- struct IOStdReq *iob;
- UWORD cmd;
- APTR data;
- ULONG len;
- {
- iob->io_Command = cmd;
- iob->io_Data = data;
- iob->io_Length = len;
- }
-
- VOID sendIO(iob,packet)
- struct IOStdReq *iob;
- struct DosPacket *packet;
- {
- iob->io_Message.mn_Node.ln_Name = (char *) packet;
- packet->dp_Link = (struct Message *) iob;
- SendIO(iob);
- }
-
- VOID returnpkt(packet,res1,res2)
- struct DosPacket *packet;
- ULONG res1,res2;
- {
- struct Message *message;
- struct MsgPort *replyport;
- struct Process *process;
-
- packet->dp_Res1 = res1;
- packet->dp_Res2 = res2;
- replyport = packet->dp_Port;
- message = packet->dp_Link;
- process = (struct Process *) FindTask(NULL);
- packet->dp_Port = &process->pr_MsgPort;
- message->mn_Node.ln_Name = (char *) packet;
- message->mn_Node.ln_Succ = NULL;
- message->mn_Node.ln_Pred = NULL;
-
- PutMsg(replyport,message);
- }
-
- /* taskwait() waits for a message to arrive at the port and
- returns the packet address */
-
- struct DosPacket *taskwait()
- {
- struct Process *process;
- struct MsgPort *port;
- struct Message *message;
-
- process = (struct Process *) FindTask(0L);
- port = &process->pr_MsgPort;
-
- /* wait for packet */
- SetSignal(FALSE,1<<8); /* clear sigbit 8 */
- while( !(message = (struct Message *) GetMsg(port)) ) Wait(1<<8);
-
- /* return the pointer to the packet */
- return((struct DosPacket *) message->mn_Node.ln_Name);
- }
-
- strlen( s )
- UBYTE *s;
- {
- int i = 0;
- while( *s++ ) i++;
- return( i );
- }
-
- strcmpi(str1, str2)
- char *str1,*str2;
- {
- UBYTE *astr =str1;
- UBYTE *bstr =str2;
- UBYTE c;
-
- while ( (c = QTOUPPER(*astr)) && (c == QTOUPPER(*bstr))) astr++, bstr++;
- if( ! c ) return ( 0 );
- if( c < *bstr ) return( -1 );
- return( 1 );
- }
-